package com.stox.ui.javafx.charting.view;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Orientation;
import javafx.scene.control.SplitPane;
import javafx.scene.input.ScrollEvent;

import org.controlsfx.control.RangeSlider;

import com.stox.ui.javafx.charting.event.handler.ChartingViewKeyEventHandler;
import com.stox.ui.javafx.charting.model.plot.VolumePlot;
import com.stox.ui.javafx.charting.widget.Chart;
import com.stox.ui.javafx.charting.widget.PrimaryChart;
import com.stox.ui.javafx.core.util.MessageSource;
import com.stox.ui.javafx.core.view.View;
import com.stox.ui.javafx.core.widget.StoxStage;

@SuppressWarnings("rawtypes")
public class ChartingView extends View {
	
	private static final List<ChartingView> chartingViews = new ArrayList<ChartingView>();
	
	private static final EventHandler<ActionEvent> viewClosedEventHandler = new EventHandler<ActionEvent>() {
		@Override
		public void handle(ActionEvent event) {
			chartingViews.remove(event.getTarget());
		}
	};
	
	public static ChartingView getSelectedChartingView() {
		for(ChartingView chartingView : chartingViews) {
			if(null != chartingView) {
				return chartingView;
			}
		}
		return null;
	}
	
	private static final EventHandler<ScrollEvent> zoomEventHandler = new EventHandler<ScrollEvent>() {
	      @Override
	      public void handle(ScrollEvent event) {
	    	  if(event.getSource() instanceof ChartingView) {
				ChartingView chartingView = (ChartingView)event.getSource();
				RangeSlider rangeSlider = chartingView.getPrimaryChart().getRangeSlider();
				
				double multiple = event.getDeltaY()/chartingView.getHeight(); 
				double lowValue = rangeSlider.getLowValue();
				double highValue = rangeSlider.getHighValue();
				
				rangeSlider.setLowValue(lowValue - lowValue*multiple);
				rangeSlider.setHighValue(highValue + highValue*multiple);
	    	  }
	      }
	};
	    
	    
	private int endIndex;
	
	private int startIndex;
	
    private double zoomStart = 0;
	
	private double zoomEnd = 1000;
	
    private VolumePlot volumePlot;
    
    private SplitPane splitPane = new SplitPane();
	
	private final List<Chart> secondaryCharts = new ArrayList<>();
	
    private final PrimaryChart primaryChart = new PrimaryChart(this);
	
	public ChartingView() {
		super(MessageSource.getMessage("Chart"));
		splitPane.setOrientation(Orientation.HORIZONTAL);
		splitPane.getItems().add(primaryChart);
		
		getContentPane().getChildren().add(splitPane);
		
		setOnKeyPressed(ChartingViewKeyEventHandler.instance);
		setOnClosedAction(viewClosedEventHandler);
		setOnScroll(zoomEventHandler);
		
		chartingViews.add(0,this);
		StoxStage.getRoot().getChildren().add(this);
	}
	
	public void update() {
		if(primaryChart == null || primaryChart.getFrontPlot() == null) return;
		
		updateZoom();
		
		primaryChart.update();
		
		for(Chart chart : secondaryCharts) 
			chart.update();
		
		paint();
	}

	public void paint() {
		if(primaryChart == null || primaryChart.getFrontPlot() == null) return;
		
		primaryChart.paint();
		
		for(Chart chart : secondaryCharts) 
			chart.paint();
	}
	
	private void updateZoom() {
		int size = primaryChart.getFrontPlot().getData().size();
		startIndex = (int)(zoomStart*size/1000);
		endIndex = (int)zoomEnd*size/1000;
	}
	
	public VolumePlot getVolumePlot() {
		return volumePlot;
	}
	
	public void setVolumePlot(VolumePlot volumePlot) {
		this.volumePlot = volumePlot;
	}
	
	public void setZoom(double low, double high) {
		if(low < 0 || low >= high || high > 1000) return;
		this.zoomStart = 1000 - high;
		this.zoomEnd = 1000 - low;
	}

	public double getZoomStart() {
		return zoomStart;
	}
	
	public double getZoomEnd() {
		return zoomEnd;
	}
	
	public PrimaryChart getPrimaryChart() {
		return primaryChart;
	}

	public int getStartIndex() {
		return startIndex;
	}
	
	public void setStartIndex(int startIndex) {
		this.startIndex = startIndex;
	}

	public int getEndIndex() {
		return endIndex;
	}
	
	public void setEndIndex(int endIndex) {
		this.endIndex = endIndex;
	}

	public List<Chart> getSecondaryCharts() {
		return Collections.unmodifiableList(secondaryCharts);
	}
	
	public void addSecondaryChart(Chart secondaryChart) {
		secondaryCharts.add(secondaryChart);
	}
	
	public void removeSecondaryChart(Chart secondaryChart) {
		secondaryCharts.remove(secondaryChart);
	}
	
	public void setZoomStart(double zoomStart) {
		this.zoomStart = zoomStart;
	}

	public void setZoomEnd(double zoomEnd) {
		this.zoomEnd = zoomEnd;
	}

}
